home *** CD-ROM | disk | FTP | other *** search
- /* @(#)src/lookup.c 1.14 9/20/92 18:45:55 */
-
- /*
- * Copyright (C) 1987, 1988 Ronald S. Karr and Landon Curt Noll
- * Copyright (C) 1992 Ronald S. Karr
- *
- * See the file COPYING, distributed with smail, for restriction
- * and warranty information.
- */
-
- /*
- * lookup.c:
- * search for values corresponding to keys using a specified
- * access method.
- *
- * external functions: open_database, close_database, lookup_database
- *
- * NeXT NetInfo aliases support added by Dan Danz <dan@az.stratus.com>
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <signal.h>
- #include <errno.h>
- #include "defs.h"
- #ifdef UNIX_BSD
- # include <sys/file.h>
- #endif
- #ifdef HAVE_YP
- # include "jump.h"
- # include <rpcsvc/ypclnt.h>
- #endif
- #include "smail.h"
- #include "lookup.h"
- #include "dys.h"
- #include "exitcodes.h"
- #ifdef HAVE_NIALIAS
- # include <aliasdb.h>
- #endif
- #ifndef DEPEND
- # include "extern.h"
- # include "debug.h"
- #endif
-
- #if defined(HAVE_DBM) && !defined(HAVE_NDBM)
- # undef NULL
- # include <dbm.h>
- # undef NULL
- # define NULL 0
- #else
- # ifdef HAVE_NDBM
- # include <ndbm.h>
- # else
- # include "sdbm.h"
- # define HAVE_NDBM
- # endif
- #endif
-
- /* functions local to this file */
- static int bsearch_open();
- static void bsearch_close();
- static int bsearch_lookup();
-
- static int lsearch_open();
- static void lsearch_close();
- static int lsearch_lookup();
-
- static int dbmbase_open();
- static void dbmbase_close();
- static int dbmbase_lookup();
-
- #ifdef HAVE_YP
- static int yp_open();
- static void yp_close();
- static int yp_lookup();
-
- static int aliasyp_open();
- static void aliasyp_close();
- static int aliasyp_lookup();
- #endif
-
- #ifdef HAVE_NIALIAS
- static int aliasni_open();
- static void aliasni_close();
- static int aliasni_lookup();
- #endif
-
-
- /*
- * the following structure defines the available access methods.
- * Methods are identified by name when open_database is called.
- */
- static struct proto {
- char *proto; /* name of the access method */
- int (*open)(); /* open database function */
- void (*close)(); /* close database function */
- int (*lookup)(); /* lookup in database function */
- } protos[] = {
- { "bsearch", /* binary search */
- bsearch_open, bsearch_close, bsearch_lookup },
- { "lsearch",
- lsearch_open, lsearch_close, lsearch_lookup },
- { "dbm", /* DBM database search */
- dbmbase_open, dbmbase_close, dbmbase_lookup },
- #ifdef HAVE_YP
- { "yp", /* YP remote database search */
- yp_open, yp_close, yp_lookup },
- { "aliasyp", /* mail.aliases-style YP database */
- aliasyp_open, aliasyp_close, aliasyp_lookup },
- #endif
- #ifdef HAVE_NIALIAS
- { "nialias", /* NetInfo remote alias search */
- aliasni_open, aliasni_close, aliasni_lookup },
- #endif /* HAVE_NIALIAS */
- };
-
- /* point to end of protos table */
- struct proto *end_protos = protos + sizeof(protos)/sizeof(protos[0]);
-
- /* generic form of structure returned by database open calls */
- struct generic_db {
- struct proto *proto; /* access method */
- };
-
- /*
- * open_database - open a database of the specified type
- *
- * given a database name and an access method return a pointer to opaque
- * data that can be used to access that database.
- *
- * return:
- * FILE_SUCCEED
- * if the open was successful. The database info will
- * be stored in *db.
- * FILE_AGAIN if the open failed but may succeed at a later time
- * (e.g., a remote host is down right now). An error will
- * be stored in *error.
- * FILE_FAIL if an unrecoverable failure occured. An error will be
- * stored in *error.
- * FILE_NOMATCH
- * if the database does not appear to exist.
- */
- int
- open_database(name, proto, retries, interval, statp, db, error)
- char *name; /* name of database */
- char *proto; /* access method name */
- int retries; /* retry count */
- int interval; /* retry interval */
- struct stat *statp; /* return a stat buffer */
- char **db; /* store open database info here */
- char **error; /* store error message here */
- {
- register struct proto *pp;
-
- for (pp = protos; pp < end_protos; pp++) {
- if (EQ(proto, pp->proto)) {
- /* found the requested access method */
- return (*pp->open)(name, pp, retries, interval, statp, db, error);
- }
- }
-
- /* access method was not found */
- *error = "unknown proto";
- return FILE_FAIL;
- }
-
- /*
- * close_database - close an open database and free its resources
- */
- void
- close_database(priv)
- char *priv; /* database's private data */
- {
- register struct generic_db *gp = (struct generic_db *)priv;
-
- (*gp->proto->close)(gp);
- }
-
- /*
- * lookup_database - find a value corresponding to a key
- *
- * given an open database, perform a lookup operation to find a match for
- * a given key.
- *
- * Return:
- * DB_SUCCEED if the lookup was successful. The matched value will
- * be stored in *value.
- * DB_NOMATCH if the lookup operation did not find a match for the key.
- * DB_AGAIN if the lookup operation failed but may succeed at a later
- * time (e.g., a remote host is down right now). An error
- * will be stored in *error.
- * DB_FAIL if an unrecoverable failure occured. An error will be
- * stored in *error.
- * FILE_AGAIN if the lookup operation failed because of an error accessing
- * the file. The file should be considered unreachable until
- * some later time.
- * FILE_FAIL if the lookup operation failed because of a permanent error
- * accessing the file. Retrying at a later time is not assumed
- * to be possible.
- */
- int
- lookup_database(db, key, value, error)
- char *db; /* open database */
- char *key; /* search key */
- char **value; /* store value here */
- char **error; /* store error message here */
- {
- register struct generic_db *gdb = (struct generic_db *)db;
-
- return (*gdb->proto->lookup)(gdb, key, value, error);
- }
-
- /*
- * bsearch access method:
- *
- * access a file containing sorted lines of data. keys
- * are at the start of each line followed by a colon and/or
- * white space.
- */
-
- /* private data: */
- struct bsearch_db {
- struct proto *proto; /* access method table entry */
- char *name; /* name of file */
- FILE *f; /* open file */
- long size; /* size of file */
- };
-
- /* bsearch_open - open a sorted file */
- static int
- bsearch_open(name, proto, retries, interval, statp, db, error)
- char *name; /* name of file */
- struct proto *proto; /* access method */
- int retries; /* retry count */
- int interval; /* retry interval */
- struct stat *statp; /* save stat results here */
- char **db; /* store open database info here */
- char **error; /* store error message here */
- {
- register struct bsearch_db *priv;
- register FILE *f;
-
- name = make_lib_fn(name);
- if (name == NULL) {
- *error = "No directory for file";
- return FILE_FAIL;
- }
- f = fopen(name, "r");
- if (f == NULL) {
- int left = retries;
-
- while (left-- > 0) {
- (void) sleep(interval);
- if (f = fopen(name, "r")) break;
- }
- if (f == NULL) {
- if (errno == ENOENT) {
- return FILE_NOMATCH;
- }
- *error = strerrno();
- return FILE_FAIL;
- }
- }
-
- #ifdef lock_fd_rd_wait
- if (lock_fd_rd_wait(fileno(f)) < 0) {
- *error = "database is locked, try again later";
- return FILE_AGAIN;
- }
- #endif
-
- /* seek to the end of the file */
- (void) fseek(f, 0L, 2);
-
- /* build the private data */
- priv = (struct bsearch_db *)xmalloc(sizeof(*priv));
- priv->proto = proto;
- priv->name = name;
- priv->f = f;
- priv->size = ftell(f); /* remember the fseek() */
- if (statp) {
- (void) fstat(fileno(f), statp);
- }
-
- *db = (char *)priv;
- return FILE_SUCCEED;
- }
-
- /* bsearch_close - close the file */
- static void
- bsearch_close(db)
- struct bsearch_db *db;
- {
- (void) fclose(db->f);
- xfree((char *)db);
- }
-
- /*
- * bsearch_lookup - look up key in ascii sorted key/data line database.
- *
- * This routine taken from smail version 2.3, though it has been
- * modified to work with the new version and has also been
- * generalized from the original routine getpath().
- */
- /*ARGSUSED*/
- static int
- bsearch_lookup(db, key, value, error)
- register struct bsearch_db *db;
- char *key;
- char **value;
- char **error;
- {
- long middle, hi, lo;
- int c;
- int flag;
- static struct str str; /* string in which to store data */
- static int str_inited = FALSE; /* TRUE if str has been STR_INIT'd */
- int i; /* temp */
-
- DEBUG1(DBG_DRIVER_HI, "bsearch_lookup: looking for <%s>\n", key);
-
- if (!str_inited) {
- /*
- * note, the string is reused in each call to bsearch.
- */
- str_inited = TRUE;
- STR_INIT(&str);
- }
-
- lo = 0;
- hi = db->size;
-
- /*
- * "Binary search routines are never written right the first time around."
- * - Robert G. Sheldon.
- * << above comment retained 'cause I thought it was cute -- tron >>
- * << it is also true -- tron >>
- */
- for( ;; ) {
- int cnt;
-
- middle = (hi + lo + 1)/2;
- (void) fseek(db->f, middle, 0); /* find midpoint */
- if (middle != 0) { /* to beginning of next line */
- while((c = getc(db->f)) != EOF && c != '\n') ;
- if (c == EOF && ferror(db->f)) {
- *error = strerrno();
- clearerr(db->f);
- return FILE_FAIL;
- }
- }
- str.i = 0;
- cnt = 0;
- while ((c = getc(db->f)) != EOF && !isspace(c) && c != ':') {
- STR_NEXT(&str, c);
- cnt++;
- }
- if (c == EOF && ferror(db->f)) {
- *error = strerrno();
- clearerr(db->f);
- return FILE_FAIL;
- }
- STR_NEXT(&str, '\0');
- flag = strcmpic(str.p, key);
- if (flag == 0)
- break;
- if ( lo>=middle ) { /* failure? */
- return DB_NOMATCH;
- }
- if ( c != EOF && flag < 0 ) { /* close window */
- lo = middle;
- } else {
- hi = middle - 1;
- }
- }
-
- /*
- * Now just copy the result.
- */
- i = -1; /* index to last non-space */
- str.i = 0; /* clear out the region */
- while(((c = getc(db->f)) != EOF) && (c != '\n')) {
- if (!isspace(c)) {
- if (c == '#') {
- /* comment puts an end to the entry */
- break;
- }
- i = str.i;
- }
- STR_NEXT(&str, c);
- }
- if (c == EOF && ferror(db->f)) {
- *error = strerrno();
- clearerr(db->f);
- return FILE_FAIL;
- }
- str.i = i + 1; /* backup to last interesting char */
- /* backup to last non-space character */
- STR_NEXT(&str, '\0');
-
- DEBUG2(DBG_DRIVER_HI, "bsearch_lookup: found <%s> for <%s>\n", str.p, key);
- *value = str.p;
- return DB_SUCCEED;
- }
-
- /*
- * lsearch access method:
- *
- * access a file containing lines of data, in the format expected
- * by read_entry() in parse.c. Keys are at the start of each line
- * followed by a colon and/or white space.
- */
-
- /* private data: */
- struct lsearch_db {
- struct proto *proto; /* access method table entry */
- char *name; /* name of file */
- FILE *f; /* open file */
- };
-
- /* lsearch_open - open a file */
- static int
- lsearch_open(name, proto, retries, interval, statp, db, error)
- char *name; /* name of file */
- struct proto *proto; /* access method */
- int retries; /* retry count */
- int interval; /* retry interval */
- struct stat *statp; /* save stat results here */
- char **db; /* store open database info here */
- char **error; /* store error message here */
- {
- register struct lsearch_db *priv;
- register FILE *f;
-
- name = make_lib_fn(name);
- if (name == NULL) {
- *error = "No directory for file";
- return FILE_FAIL;
- }
- f = fopen(name, "r");
- if (f == NULL) {
- int left = retries;
-
- while (left-- > 0) {
- (void) sleep(interval);
- if (f = fopen(name, "r")) break;
- }
- if (f == NULL) {
- if (errno == ENOENT) {
- return FILE_NOMATCH;
- }
- *error = strerrno();
- return FILE_FAIL;
- }
- }
-
- #ifdef lock_fd_rd_wait
- if (lock_fd_rd_wait(fileno(f)) < 0) {
- *error = "database is locked, try again later";
- return FILE_AGAIN;
- }
- #endif
-
- /* build the private data */
- priv = (struct lsearch_db *)xmalloc(sizeof(*priv));
- priv->proto = proto;
- priv->name = name;
- priv->f = f;
- if (statp) {
- (void) fstat(fileno(f), statp);
- }
-
- *db = (char *)priv;
- return FILE_SUCCEED;
- }
-
- /* lsearch_close - close the file */
- static void
- lsearch_close(db)
- struct lsearch_db *db;
- {
- (void) fclose(db->f);
- xfree((char *)db);
- }
-
- /*
- * lsearch_lookup - look up key with a linear search
- */
- /*ARGSUSED*/
- static int
- lsearch_lookup(db, key, value, error)
- register struct lsearch_db *db;
- char *key;
- char **value;
- char **error;
- {
- int len = strlen(key); /* length of comparison */
- register char *entry; /* entry from read_entry() */
- register char *p; /* temp */
-
- DEBUG1(DBG_DRIVER_HI, "lsearch_lookup: looking for <%s>\n", key);
-
- /* always start from the beginning of the file */
- (void) fseek(db->f, 0L, 0);
-
- while (entry = read_entry(db->f)) {
- if (strncmpic(entry, key, len) == 0 &&
- (entry[len] == ':' || isspace(entry[len])))
- {
- char *ret; /* value to be returned */
-
- /* found a matching entry in the file, find the data */
- entry += len;
- /*
- * skip <whitespace>:<whitespace>
- */
- while (isspace(*entry)) entry++;
- if (*entry == ':') {
- entry++;
- while (isspace(*entry)) entry++;
- }
-
- /*
- * skip comments
- */
- while (*entry == '#') {
- while (*entry && *entry != '\n') entry++;
- while (isspace(*entry)) entry++;
- }
- ret = entry; /* return from this point on */
-
- /* though do some more processing to the remainder */
- p = entry - 1;
- /* find the last character which is not white-space or comment */
- while (*entry) {
- if (!isspace(*entry)) {
- if (*entry == '#') {
- while (*entry && *entry != '\n') entry++;
- continue;
- }
- p = entry;
- }
- entry++;
- }
- /* throw away after the last interesting character */
- p[1] = '\0';
-
- DEBUG1(DBG_DRIVER_HI, "lsearch_lookup: return <%s>\n", ret);
-
- *value = ret;
- return DB_SUCCEED;
- }
- }
- if (ferror(db->f)) {
- *error = strerrno();
- return FILE_FAIL;
- }
- DEBUG1(DBG_DRIVER_HI, "lsearch_lookup: did not find <%s>\n", key);
- return DB_NOMATCH;
- }
-
- /*
- * dbmbase access method:
- *
- * access a database stored as a DBM database. Note that the
- * DBM semantics only allow for one DBM file in the life of
- * a process. As a result, these files should never be closed
- * and only one reference to a DBM-type database can exist in
- * the application.
- *
- * BUGS: extensive use of #ifdef within functions is ugly.
- */
-
- /*
- * form for private data:
- */
- struct dbmbase_db {
- struct proto *proto; /* access method table entry */
- char *name; /* name of database */
- #ifdef HAVE_NDBM
- DBM *db; /* open database */
- #endif
- };
-
- #ifndef HAVE_NDBM
- static struct dbmbase_db *opendb = NULL;
- #endif
-
- /* dbmbase_open - open a DBM database */
- static int
- dbmbase_open(name, proto, retries, interval, statp, db, error)
- char *name; /* name of database */
- struct proto *proto; /* access method */
- int retries; /* retry count */
- int interval; /* retry interval */
- struct stat *statp; /* return a stat structure */
- char **db; /* store open database info here */
- char **error; /* store error message here */
- {
- char *pag_file; /* name of .pag file */
- register struct dbmbase_db *priv;
-
- name = make_lib_fn(name);
- if (name == NULL) {
- *error = "No directory for file";
- return FILE_FAIL;
- }
- priv = (struct dbmbase_db *)xmalloc(sizeof(*priv));
-
- #ifndef HAVE_NDBM
- if (opendb != NULL) {
- dbmclose();
- opendb = NULL;
- }
- #endif
-
- #ifdef HAVE_NDBM
- if ((priv->db = dbm_open(name, 0, 0)) == NULL)
- #else
- if (dbminit(name) < 0)
- #endif
- {
- int succeed = FAIL;
- int left = retries;
-
- if (left < 1) {
- /* DBM databases cannot be moved atomicly, so require
- * at least two retries */
- left = 2;
- }
- if (interval < 2) {
- /* require a somewhat reasonable interval as well */
- interval = 2;
- }
-
- while (left-- > 0) {
- (void) sleep(interval);
- #ifdef HAVE_NDBM
- if ((priv->db = dbm_open(name, 0, 0)) != NULL)
- #else
- if (dbminit(name) == 0)
- #endif
- {
- succeed = SUCCEED;
- break;
- }
- if (errno != ENOENT) {
- break;
- }
- }
- if (succeed != DB_SUCCEED) {
- if (errno == ENOENT)
- return FILE_NOMATCH;
- *error = strerrno();
- return FILE_FAIL;
- }
- }
-
- #ifndef HAVE_NDBM
- opendb = priv;
- #endif
-
- /* if required, get a stat structure from the .pag file */
- if (statp) {
- pag_file = xmalloc(strlen(name) + sizeof(".pag"));
- (void) sprintf(pag_file, "%s.pag", name);
- (void) stat(pag_file, statp);
- xfree(pag_file);
- }
- priv->proto = proto;
- priv->name = name;
- *db = (char *)priv;
- #if defined(HAVE_NDBM) && defined(lock_fd_rd_wait)
- if (lock_fd_rd_wait(dbm_pagfno(priv->db)) < 0) {
- *error = "database is locked, try again later";
- return FILE_AGAIN;
- }
- #endif /* HAVE_NDBM && lock_fd_rd_wait */
- return FILE_SUCCEED;
- }
-
- /* dbmbase_close - close the database */
- static void
- dbmbase_close(db)
- struct dbmbase_db *db;
- {
- #ifdef HAVE_NDBM
- (void) dbm_close(db->db);
- #else
- if (opendb == db) {
- dbmclose();
- opendb = NULL;
- }
- #endif
- xfree((char *)db);
- return;
- }
-
- /* dbmbase_lookup - call on the DBM routines to find that data */
- static int
- dbmbase_lookup(db, key, value, error)
- register struct dbmbase_db *db;
- char *key;
- char **value;
- char **error;
- {
- datum the_key;
- datum the_value;
- static int temp_size; /* size of temp_key area */
- static char *temp_data = NULL; /* growable temp area */
- int len; /* length of key */
- register char *p;
-
- #ifndef HAVE_NDBM
- if (opendb != db) {
- if (opendb) {
- dbmclose();
- opendb = NULL;
- }
- if (dbminit(db->name) < 0)
- return FAIL;
- }
- #endif
-
- /*
- * convert the key to lower case, as fetch() is case-sensitive
- * for efficiency, keep around the malloc'd region used to store
- * the down-cased key.
- */
- len = strlen(key) + 1;
- if (temp_data == NULL) {
- temp_size = len;
- temp_data = xmalloc(temp_size);
- } else if (temp_size < len) {
- temp_size = len;
- temp_data = xrealloc(temp_data, temp_size);
- }
- for (p = temp_data; *key; p++, key++) {
- *p = lowercase(*key);
- }
- *p = '\0';
-
- the_key.dptr = temp_data;
- the_key.dsize = len;
- #ifdef HAVE_NDBM
- the_value = dbm_fetch(db->db, the_key);
- if (dbm_error(db->db)) {
- *error = xprintf("Error in fetching %s", the_key);
- return FILE_FAIL;
- }
- #else
- the_value = fetch(the_key);
- #endif
-
- if (the_value.dptr) {
- if (temp_size < the_value.dsize + 1) {
- temp_size = the_value.dsize + 1;
- temp_data = xrealloc(temp_data, temp_size);
- }
- (void) strcpy(temp_data, the_value.dptr);
- *value = temp_data;
- return DB_SUCCEED;
- }
- return DB_NOMATCH;
- }
-
- #ifdef HAVE_YP
- /*
- * The YP database routines takes names of the form:
- *
- * domain:database_name
- * or database_name
- *
- * in the former case, the `domain' specified is the YP domain to use
- * for yp_match operations. In the second case, the default YP domain
- * is used.
- *
- * There are two forms for the lookup: regular yp and aliasyp. The
- * second form is used for accessing the standard Sun mail.aliases map
- * format, which does not fit the form of other YP maps. The
- * difference is that a nul-byte is counted in the length of a key for
- * mail.aliases, while it is not counted for other maps.
- */
-
- /*
- * form for private data:
- */
- struct yp_db {
- struct proto *proto; /* access method table entry */
- char *map; /* name of database */
- char *domain; /* yp domain */
- };
-
- static char *default_yp_domain = NULL; /* from yp_get_default_domain(3N) */
- static int common_yp_lookup();
-
- #ifdef notyet
- static JUMP_ENVBUF alarm_jmp; /* jump here on SIGALRM */
-
- static void yp_sigalrm(); /* catch SIGALRM for YP timeouts */
-
- #define YP_TIMEOUT 30 /* 30 second timeout for YP */
- #endif
-
- /*
- * yp_open, aliasyp_open - create a yp_private structure for a database
- *
- * yp_order(3N) is called to verify that the database is accessible.
- */
- static int
- aliasyp_open(name, proto, retries, interval, statp, db, error)
- char *name; /* name of database */
- struct proto *proto; /* access method */
- int retries; /* retry count */
- int interval; /* retry interval */
- struct stat *statp; /* return a stat structure */
- char **db; /* store open database info here */
- char **error; /* store error message here */
- {
- return yp_open(name, proto, retries, interval, statp, db, error);
- }
-
- /*ARGSUSED*/
- static int
- yp_open(name, proto, retries, interval, statp, db, error)
- char *name; /* name of database */
- struct proto *proto; /* access method */
- int retries; /* retry count */
- int interval; /* retry interval */
- struct stat *statp; /* return a stat structure */
- char **db; /* store open database info here */
- char **error; /* store error message here */
- {
- register struct yp_db *priv;
- register char *p;
- int err; /* error from yp functions */
- int order; /* output from yp_order */
- char *domain;
- #ifdef notyet
- VOLATILE int save_time; /* saved value from alarm() */
- VOLATILE JUMPSIG save_sigalrm; /* previous SIGALRM handler */
- #endif
-
- priv = (struct yp_db *)xmalloc(sizeof(*priv));
-
- /* is a YP domain specified? */
- p = index(name, ':');
- if (p == NULL) {
- /* no, use the default YP domain */
- priv->domain = NULL;
- priv->map = name;
- } else {
- /* yes, make a copy and use it */
- priv->domain = xmalloc(p - name + 1);
- (void) memcpy(priv->domain, name, p - name);
- priv->domain[p - name] = '\0';
- priv->map = p + 1;
- }
-
- /* if stat required, just zero it out, there is nothing to put there */
- if (statp) {
- (void) bzero((char *)statp, sizeof(*statp));
- }
-
- if (priv->domain) {
- domain = priv->domain;
- } else {
- if (default_yp_domain == NULL &&
- (err = yp_get_default_domain(&default_yp_domain)))
- {
- /* this should only fail if the domainname is not set, right? */
- *error = yperr_string(err);
- return FILE_FAIL;
- }
- domain = default_yp_domain;
- }
-
- #ifdef notyet
- save_time = alarm(0);
-
- /* verify that we can access the database */
- if (JUMP_SETJMP(alarm_jmp)) {
- (void) alarm(0);
- JUMP_CLEARSIG(SIGALRM, &save_sigalrm);
- if (save_time) {
- (void) alarm(save_time);
- }
-
- *error = "YP timeout";
- return FILE_AGAIN;
- } else {
-
- /* arrange to timeout if the operation blocks */
- JUMP_SETSIG(SIGALRM, yp_sigalrm, &save_sigalrm);
- (void) alarm(YP_TIMEOUT);
- #endif
-
- /* potentially blocking operation */
- err = yp_order(domain, priv->map, &order);
-
- #ifdef notyet
- /* restore previous alarm setting */
- (void) alarm(0);
- JUMP_CLEARSIG(SIGALRM, &save_sigalrm);
- if (save_time) {
- (void) alarm(save_time);
- }
- #endif
-
- if (err) {
- /* analyze the reason for the failure */
- *error = yperr_string(err);
- switch (err) {
- case YPERR_RPC: /* cases where failure is temporary */
- case YPERR_YPERR:
- case YPERR_RESRC:
- case YPERR_PMAP:
- case YPERR_YPBIND:
- case YPERR_YPSERV:
- return FILE_AGAIN;
-
- case YPERR_MAP: /* no such map */
- case YPERR_DOMAIN: /* no such domain */
- return FILE_NOMATCH;
- }
- return FILE_FAIL;
- }
- #ifdef notyet
- }
- #endif
-
- priv->proto = proto;
- *db = (char *)priv;
- return FILE_SUCCEED;
- }
-
- /* yp_close, aliasyp_close - free up data allocated for to a YP database */
- static void
- aliasyp_close(db)
- struct yp_db *db;
- {
- yp_close(db);
- }
-
- /*ARGSUSED*/
- static void
- yp_close(db)
- struct yp_db *db;
- {
- if (db->domain) {
- xfree(db->domain);
- }
- xfree((char *)db);
- return;
- }
-
- /* yp_lookup, aliasyp_lookup - call on the YP routines to find that data */
- static int
- yp_lookup(db, key, value, error)
- register struct yp_db *db; /* open YP database */
- char *key; /* search key */
- char **value; /* return value here */
- char **error; /* return error message here */
- {
- return common_yp_lookup(db, key, value, error, FALSE);
- }
-
- static int
- aliasyp_lookup(db, key, value, error)
- register struct yp_db *db; /* open YP database */
- char *key; /* search key */
- char **value; /* return value here */
- char **error; /* return error message here */
- {
- return common_yp_lookup(db, key, value, error, TRUE);
- }
-
- /*ARGSUSED*/
- static int
- common_yp_lookup(db, key, value, error, aliasflag)
- register struct yp_db *db; /* open YP database */
- char *key; /* search key */
- char **value; /* return value here */
- char **error; /* return error message here */
- int aliasflag; /* TRUE for Sun mail.aliases format */
- {
- int keylen; /* length of key */
- static char *temp_key = NULL; /* area for lower-case conversion */
- static int temp_size; /* size of temp area */
- register char *p;
- char *matchval; /* matched data */
- int matchlen; /* length of matched data */
- int err; /* yp error */
- char *domain;
- #ifdef notyet
- VOLATILE int save_time; /* saved value from alarm() */
- VOLATILE JUMPSIG save_sigalrm; /* previous SIGALRM handler */
- #endif
-
- /*
- * convert the key to lower case, as fetch() is case-sensitive
- * for efficiency, keep around the malloc'd region used to store
- * the down-cased key.
- */
- keylen = strlen(key);
- if (temp_key == NULL) {
- temp_size = keylen + 1;
- temp_key = xmalloc(temp_size);
- } else if (temp_size <= keylen) {
- temp_size = keylen + 1;
- temp_key = xrealloc(temp_key, temp_size);
- }
- for (p = temp_key; *key; p++, key++) {
- *p = lowercase(*key);
- }
- *p = '\0';
-
- if (db->domain) {
- domain = db->domain;
- } else {
- domain = default_yp_domain;
- }
-
- if (aliasflag) {
- keylen++;
- }
-
- #ifdef notyet
- save_time = alarm(0);
-
- if (JUMP_SETJMP(alarm_jmp)) {
- (void) alarm(0);
- JUMP_CLEARSIG(SIGALRM, &save_sigalrm);
- if (save_time) {
- (void) alarm(save_time);
- }
-
- *error = "YP timeout";
- return FILE_AGAIN;
- } else {
-
- /* arrange to timeout if the operation blocks */
- JUMP_SETSIG(SIGALRM, yp_sigalrm, &save_sigalrm);
- (void) alarm(YP_TIMEOUT);
- #endif
-
- /* potentially blocking operation */
- err = yp_match(domain, db->map, temp_key, keylen,
- &matchval, &matchlen);
-
- #ifdef notyet
- /* restore previous alarm setting */
- (void) alarm(0);
- JUMP_CLEARSIG(SIGALRM, &save_sigalrm);
- if (save_time) {
- (void) alarm(save_time);
- }
- #endif
-
- if (err) {
- /* analyze the reason for the failure */
- *error = yperr_string(err);
- switch (err) {
- case YPERR_RPC: /* cases where failure is temporary */
- case YPERR_DOMAIN:
- case YPERR_YPERR:
- case YPERR_RESRC:
- case YPERR_PMAP:
- case YPERR_YPBIND:
- case YPERR_YPSERV:
- return FILE_AGAIN;
-
- case YPERR_KEY: /* key not in database */
- return DB_NOMATCH;
- }
- return FILE_FAIL;
- }
- #ifdef notyet
- }
- #endif
-
- matchval[matchlen] = '\0'; /* we don't want the extra newline */
- *value = matchval;
- return DB_SUCCEED;
- }
-
- #ifdef notyet
- static void
- yp_sigalrm()
- {
- JUMP_LONGJMP(alarm_jmp, 1);
- }
- #endif
-
- #endif /* HAVE_YP */
-
- #ifdef HAVE_NIALIAS
-
- /*
- * nialias access method
- *
- * access the netinfo alias database.
- *
- */
-
- /* private data: */
- struct aliasni_db {
- struct proto *proto;
- char *expansion_area;
- int expansion_size;
- };
-
- /* aliasni_open - open the netinfo database */
-
- static int
- aliasni_open(name, proto, retries, interval, statp, db, error)
- char *name; /* name of file */
- struct proto *proto; /* access method */
- int retries; /* retry count */
- int interval; /* retry interval */
- struct stat *statp; /* save stat results here */
- char **db; /* store open database info here */
- char **error; /* store error message here */
- {
- register struct aliasni_db *priv;
-
- /* build the private area */
-
- alias_setent();
-
- priv = (struct aliasni_db *)xmalloc(sizeof(*priv));
- priv->proto = proto;
- priv->expansion_area = NULL;
- priv->expansion_size = 0;
-
- *db = (char *)priv;
- /* always succeeds */
- return FILE_SUCCEED;
- }
-
- /* aliasni_close - close the NetInfo alias database */
- static void
- aliasni_close(db)
- struct aliasni_db *db;
- {
- alias_endent();
- xfree(db->expansion_area);
- xfree((char *)db);
- }
-
- /* aliasni_lookup - search for a key in the NetInfo alias database */
-
- /*ARGSUSED*/
- static int
- aliasni_lookup(db, key, value, error)
- register struct aliasni_db *db;
- char *key;
- char **value;
- char **error;
- {
- aliasent *a;
- int i,n;
- char *p;
-
- DEBUG1(DBG_DRIVER_HI, "aliasni_lookup: looking for <%s>\n",key);
-
- a = alias_getbyname(key);
- if ((!a) || (a->alias_members_len == 0)) {
- DEBUG1(DBG_DRIVER_HI,"aliasni_lookup: looking for <%s>\n",
- lc_fold(key));
- a = alias_getbyname(lc_fold(key));
- if ((!a) || (a->alias_members_len == 0)) {
- DEBUG1(DBG_DRIVER_HI,"aliasni_lookup: did not find <%s>\n",key);
- return DB_NOMATCH;
- }
- }
-
- /* Since this routine can return multiple member lists, then */
- /* we must expand it into a single string and then let the caller */
- /* parse it into the individual fields */
-
- /* calculate the size of the expansion area */
- for (n=2,i=0;i < a->alias_members_len; i++)
- n += (strlen(a->alias_members[i])+1);
-
- if (db->expansion_size < n) {
- db->expansion_size = n;
- if (db->expansion_area)
- db->expansion_area=xrealloc(db->expansion_area, db->expansion_size);
- else
- db->expansion_area=xmalloc(db->expansion_size);
- }
-
- for (p = db->expansion_area, i=0; i < a->alias_members_len; i++)
- if (n = strlen(a->alias_members[i])) {
- *p++ = ','; /* add a separator */
- memcpy(p,a->alias_members[i],n); /* add these member(s) */
- p += n;
- }
- *p = '\0'; /* terminate the string */
-
- /* if anything in the string, skip the opening separator */
- *value = (p == db->expansion_area)?p:db->expansion_area+1;
-
- DEBUG3(DBG_DRIVER_HI, "aliasni_lookup: returns %d %s <%s>\n",
- a->alias_members_len, (a->alias_local?"local":"network"),*value);
-
- return DB_SUCCEED;
- }
-
- #endif /* HAVE_NIALIAS */
-
- #ifdef STANDALONE
-
- int debug = 0;
- FILE *errfile = stderr;
-
- void
- main(argc, argv)
- int argc;
- char **argv;
- {
- char *program = (--argc, *argv++);
- char *proto;
- char *name;
- char *db;
- char *error;
- int interval = 3;
- int retries = 0;
- int success;
-
- for (;;) {
- if (*argv && EQ(*argv, "-r")) {
- argv++;
- retries = atoi(*argv++);
- argc -= 2;
- continue;
- }
- if (*argv && EQ(*argv, "-i")) {
- argv++;
- interval = atoi(*argv++);
- argc -= 2;
- continue;
- }
- break;
- }
-
- if (argc < 3) {
- fprintf(stderr,
- "Usage: %s [-r #retries] [-i interval] proto name key ...\n",
- program);
- exit(EX_USAGE);
- }
-
- proto = *argv++;
- name = *argv++;
-
- success = open_database(name, proto, retries, interval,
- (struct stat *)NULL, &db, &error);
- switch (success) {
- case DB_AGAIN:
- fprintf(stderr, "%s: try again later: %s\n", program, error);
- exit(EX_TEMPFAIL);
-
- case DB_FAIL:
- fprintf(stderr, "%s: open failed: %s\n", program, error);
- exit(EX_UNAVAILABLE);
- }
-
- while (*argv) {
- char *value;
-
- switch (lookup_database(db, *argv, &value, &error)) {
- case DB_AGAIN:
- fprintf(stderr, "%s: %s: try again later: %s\n",
- program, *argv, error);
- break;
-
- case DB_FAIL:
- fprintf(stderr, "%s: %s: failed: %s\n", program, *argv, error);
- break;
-
- case DB_NOMATCH:
- fprintf(stderr, "%s: %s: no match\n", program, *argv);
- break;
-
- case DB_SUCCEED:
- printf("%s --> %s", *argv, value);
- break;
- }
- argv++;
- }
-
- close_database(db);
- exit(EX_OK);
- }
-
- char *
- xmalloc(size)
- int size;
- {
- char *malloc();
-
- return malloc(size);
- }
-
- char *
- xrealloc(region, size)
- char *region;
- int size;
- {
- char *realloc();
-
- return realloc(region, size);
- }
-
- void
- xfree(region)
- char *region;
- {
- (void) free(region);
- }
- #endif /* STANDALONE */
-